/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_zml.htm
 *
 * Zhiqim Zml is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.zml.statement;

import java.util.ArrayList;
import java.util.List;

import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.zml.Statement;
import org.zhiqim.zml.StatementNesting;
import org.zhiqim.zml.StatementParser;
import org.zhiqim.zml.ZmlVariable;
import org.zhiqim.zml.Zmls;
import org.zhiqim.zml.exception.StatementException;
import org.zhiqim.zml.statement._Return.ReturnException;

/**
 * 函数定义语句，格式为：
 * 
 * <#function name(param1, param2)>
 * 
 * </#function>
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class _Function extends Statement implements StatementNesting
{
    private String name;
    private String path;
    private ArrayList<String> variableNameList;
    private List<Statement> stmtList;
    
    //是否开始指令独占一行
    private boolean isBeginExclusiveLine;
    
    private transient String content;
    private transient int contentBeginIndex;
    
    public _Function()
    {//ZML内部函数
        this.variableNameList = new ArrayList<String>();
    }
    
    public _Function(String path)
    {//全局函数
        this.path = path;
        this.variableNameList = new ArrayList<String>();
    }

    /** 全局函数定义需要path，这样就不需要到zml中去找 */
    public String getPath()
    {
        return path;
    }
    
    @Override
    public boolean isNesting()
    {
        return true;
    }
    
    @Override
    public boolean isExclusiveLine() throws StatementException
    {//父类判断是false的一定是false，=true的子类判断
        return super.isExclusiveLine()?isBeginExclusiveLine:false;
    }
    
    @Override
    public void parseStatement() throws StatementException
    {
        String s = Strings.trim(getStatement(), FUNCTION_BEGIN, FUNCTION_END);
        int ind = s.indexOf(TAG_END);
        if (ind == -1)
            throw new StatementException(this, FUNCTION + "未找到单行结束符");

        String expression = Strings.formatSpace(s.substring(0, ind));
        int indName = expression.indexOf("(");
        if (indName == -1)
            throw new StatementException(this, FUNCTION + "未找到函数名");
        
        //找到函数名
        name = expression.substring(0, indName).trim();
        
        //找到函数形参
        String params = expression.substring(indName).trim();
        params = Strings.trim(Strings.trim(params, "(", ")"));
        if (!Validates.isEmpty(params))
        {
            String[] paramArr = params.split(",");
            for (String param : paramArr)
            {
                variableNameList.add(param.trim());
            }
            variableNameList.trimToSize();
        }
        
        //对函数内的内容进行嵌套检查，得到嵌套语句列表
        content = s.substring(ind + 1);
        int brNum = Strings.getStartsWithBrNum(content);
        if (brNum > 0)
        {//删除<#function>之后的首个\r\n
            content = content.substring(brNum);
        }
        
        isBeginExclusiveLine = brNum > 0;
        contentBeginIndex = getBeginIndex() + FUNCTION_BEGIN.length() + ind + 1 + brNum;
        
        content = Zmls.removeRightMaybeEmptyBlankLine(content);
        stmtList = StatementParser.parseStatementNesting(this);
        content = null;//清除临时数据
    }
    
    @Override
    public String process(ZmlVariable variableMap) throws StatementException
    {
        variableMap.addFunction(this);
        
        //本身执行不返回文本，在build中调用返回文本
        return null;
    }
    
    /**
     * 在_Method中调用返回文本
     * 
     * @param variableMap           变量表
     * @return                      函数结果字符串
     * @throws StatementException   语句异常
     */
    public Object build(ZmlVariable variableMap) throws StatementException
    {
        StringBuilder strb = new StringBuilder();
        
        try
        {
            StatementParser.processStatementList(stmtList, variableMap, strb);
            return strb.toString();
        }
        catch(ReturnException e)
        {
            return e.hasValue()?e.getValue():strb.toString();
        }
    }
    
    public String getName()
    {
        return name;
    }
    
    public List<String> getVariableNameList()
    {
        return variableNameList;
    }
    
    /**********************************************/
    //两个临时数据，用于语句解析成嵌套语句列表
    /**********************************************/
    
    @Override
    public String getContent()
    {
        return content;
    }

    @Override
    public int getContentBeginIndex()
    {
        return contentBeginIndex;
    }
    
    @Override
    public String getPrevStatement(Statement stmt) throws StatementException
    {
        int ind = stmtList.indexOf(stmt);
        if (ind <= 0)
            return null;
        
        return stmtList.get(ind-1).getStatement();
    }
    
    @Override
    public String getNextStatement(Statement stmt) throws StatementException
    {
        int ind = stmtList.indexOf(stmt);
        if (ind == -1 || ind >= stmtList.size()-1)
            return null;
        
        return stmtList.get(ind+1).getStatement();
    }
}
